package io.gitee.baicaixiaozhan.httpmessageconverter.jackson;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import io.gitee.baicaixiaozhan.httpmessageconverter.annotation.Desensitize;
import io.gitee.baicaixiaozhan.httpmessageconverter.kit.ReplaceKit;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.SpelParserConfiguration;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.lang.annotation.Annotation;

/**
 * DESC: 数据脱敏 Jackson 实现
 *
 * @author baicaixiaozhan
 * @since v1.0.0
 */
public class DesensitizeSerializer extends JsonSerializer<CharSequence> {

    private static final String VARIABLE = "str";

    private final Annotation annotation;
    private SpelParserConfiguration config;
    private ExpressionParser parser;

    public DesensitizeSerializer(Annotation annotation) {
        this.annotation = annotation;
        this.config = new SpelParserConfiguration(true, true);
        this.parser = new SpelExpressionParser(this.config);
    }

    @Override
    public void serialize(CharSequence value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (StringUtils.isEmpty(value)) {
            gen.writeObject(value);
            return;
        }

        Desensitize desensitize = (Desensitize) annotation;
        char delimiter = desensitize.delimiter();
        String result;
        switch (desensitize.pattern()) {
            case FULL_NAME:
                result = ReplaceKit.replace(value, 1, value.length(), delimiter);
                break;
            case ID_CARD:
                result = ReplaceKit.replace(value, 1, value.length() - 1, delimiter);
                break;
            case MOBILE_PHONE:
                result = ReplaceKit.replace(value, 3, value.length() - 4, delimiter);
                break;
            case FIXED_TELEPHONE:
                result = ReplaceKit.replace(value, 4, value.length() - 2, delimiter);
                break;
            case EMAIL:
                result = ReplaceKit.replace(value, 1, String.valueOf(value).indexOf("@"), delimiter);
                break;
            case RANGE:
                result = ReplaceKit.replace(value,
                        expressionIndex(value, desensitize.start()),
                        expressionIndex(value, desensitize.end()), delimiter);
                break;
            default:
                result = ReplaceKit.replace(value, 0, value.length(), delimiter);
        }
        gen.writeObject(result);
    }

    private Integer expressionIndex(CharSequence source, String expressionString) {
        StandardEvaluationContext context = new StandardEvaluationContext();
        context.setVariable(VARIABLE, source);
        Expression exp = parser.parseExpression(expressionString);
        return exp.getValue(context, Integer.class);
    }
}